#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/sendfile.h>
#include "test.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define BLOG_FILE_NAME "../../blog.txt"

off_t get_file_size(const char *filename)
{
    struct stat st;
    if (stat(filename, &st) == -1)
    {
        return 0;
    }
    return st.st_size;
}

int connect_tcpserver(const char *ip, unsigned short port);


int send_file_data(int sockfd, char *filename, off_t start_offset, size_t send_file_size)
{
    LOG("send_file_data: %s\n", filename);
    int file_fd = open(filename, O_RDONLY);
    if (file_fd == -1)
    {
        perror("master: open file failed");
        return -1;
    }

    off_t ret = lseek(file_fd, start_offset, SEEK_SET);
    if (ret == -1)
    {
        perror("lseek failed");
        close(file_fd);
        return -1;
    }

    off_t total_send = 0;
    ssize_t sent_len;
    while (total_send < send_file_size)
    {
        //LOG("total_len: %ld, send_file_size: %ld\n", total_send, send_file_size);
        sent_len = sendfile(sockfd, file_fd, NULL, send_file_size - total_send);
        if (sent_len == -1)
        {
            if (errno == EINTR)
                continue;
            perror("master: sendfile failed");
            close(file_fd);
            return -1;
        }
        total_send += sent_len;
    }
    close(file_fd);

    return total_send; // 返回发送的数据大小
}


int send_msg(int connfd, char *msg, int length)
{

    int res = send(connfd, msg, length, 0);
    if (res < 0)
    {
        perror("send");
        exit(1);
    }
    return res;
}

int recv_msg(int connfd, char *msg, int length)
{

    int res = recv(connfd, msg, length, 0);
    // LOG("res: %s\n", msg);
    if (res < 0)
    {
        perror("recv");
        exit(1);
    }
    //LOG("recv_len: %d\n", res);

    return res;
}

int connect_tcpserver(const char *ip, unsigned short port)
{

    int connfd = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in tcpserver_addr;
    memset(&tcpserver_addr, 0, sizeof(struct sockaddr_in));

    tcpserver_addr.sin_family = AF_INET;
    tcpserver_addr.sin_addr.s_addr = inet_addr(ip);
    tcpserver_addr.sin_port = htons(port);

    int ret = connect(connfd, (struct sockaddr *)&tcpserver_addr, sizeof(struct sockaddr_in));
    if (ret)
    {
        perror("connect");
        return -1;
    }

    return connfd;
}
// ./test_set
int main(int argc, char *argv[])
{
    int connfd = connect_tcpserver(IP, PORT);

    //int connfd = connect_tcpserver(TEST_IP, TEST_PORT);
    if (send_msg(connfd, "RSET blog ", strlen("RSET blog ")) != strlen("RSET blog "))
    {
        close(connfd);
        LOG("fail\n");
        return -1;
    }
    off_t file_size = get_file_size(BLOG_FILE_NAME);

    int send_len = send_file_data(connfd, BLOG_FILE_NAME, 0, file_size);
    if (send_len != file_size)
    {
        close(connfd);
        LOG("fail\n");
        return -1;
    }

    if (send_msg(connfd, "\x03", strlen("\x03")) != strlen("\x03"))
    {
        close(connfd);
        LOG("fail\n");
        return -1;
    }

    char buffer[128] = {0};
    if (recv_msg(connfd, buffer, strlen("RSET SUCCESS\r\n")) != strlen("RSET SUCCESS\r\n"))
    {
        close(connfd);
        LOG("fail\n");
        return -1;
    }
    
    if (strcmp("RSET SUCCESS\r\n", buffer) != 0)
    {

        close(connfd);
        LOG("fail: buffer: %s, buffer_len: %ld\n", buffer, strlen(buffer));
        return -1;
    }

    close(connfd);
    LOG("success set blog: %ld bytes\n", file_size);

    return 0;
}
